package com.sh.personnel.util;

import com.sh.personnel.security.ISecurityUser;
import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.*;

/**
 * jwt工具类
 * @author 林思浩
 * @date 2020/02/26 11:00
 */
@Component
public class JwtUtil implements Serializable {

    private static final String USERID = "userid"; //用户id
    private static final String USERNAME = "username"; //用户工号
    private static final String AUTHORITIES = "authorities"; //权限列表
    private static final String CREATETIME = "created"; //创建时间
    private static final long EXPIRETIME = 60 * 60 * 1000; //有效时间1hour
    private static final String SECRET = "klaythompson"; //密钥

    @Value("${jwt.header}")
    private String jwtHeader;

    @Value("${jwt.tokenHead}")
    private String jwtPreHead;

    /**
     * 生成令牌token
     * @param securityUser
     * @return
     */
    public static String generateToken(ISecurityUser securityUser) {
        Map<String, Object> claims = new HashMap<>(3);
        claims.put(USERID, securityUser.getUserId());
        claims.put(USERNAME, securityUser.getUsername());
        claims.put(AUTHORITIES, securityUser.getAuthorities());
        claims.put(CREATETIME, new Date());
        return Jwts.builder()
                .setClaims(claims)
                .setSubject(securityUser.getUsername())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRETIME))
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .compact();
    }

    /**
     * 根据请求request获取登录认证信息
     * @param request
     * @return
     */
    public ISecurityUser getUserFromToken(HttpServletRequest request) {
        String token = request.getHeader(jwtHeader);
        if(!StringUtils.isEmpty(token)) {
            token = token.substring(jwtPreHead.length());
            Claims claims = getClaimsFromToken(token);
            if(validateToken(claims, token)) {
                Collection<GrantedAuthority> authorities = (Collection<GrantedAuthority>) claims.get(AUTHORITIES);
                String userId = (String) claims.get(USERID);
                String username = claims.getSubject();
                return new ISecurityUser(userId, username, null, authorities);
            }
        }
        return null;
    }

    /**
     * 验证令牌
     * @param token
     * @return
     */
    public static Boolean validateToken(Claims claims, String token) {
        if(claims != null && claims.getSubject() != null && isTokenExpired(token)) {
            return true;
        }
        return false;
    }

    /**
     * 校验令牌是否过期
     * @param token
     * @return
     */
    public static Boolean isTokenExpired(String token) {
        try {
            Claims claims = getClaimsFromToken(token);
            Date expiration = claims.getExpiration();
            return new Date().before(expiration);
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 根据请求令牌获取登录认证信息
     * @param token
     * @return
     */
    public static String getUserFromToken(String token) {
        return getClaimsFromToken(token).getSubject();
    }

    /**
     * 根据令牌获取用户数据声明
     * @param token
     * @return
     */
    public static Claims getClaimsFromToken(String token) {
        Claims claims = null;
        try {
            claims = Jwts.parser().setSigningKey(SECRET)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (ExpiredJwtException e) {
            System.out.println("jwt过期");
        } catch(MalformedJwtException e) {
            System.out.println("jwt无效");
        }
        return claims;
    }


}
